package com.hydra.framework.event.kvo.list;

import android.os.Looper;

import com.hydra.framework.thread.ThreadBus;
import com.hydra.framework.event.kvo.KvoSource;

import java.util.Collection;
import java.util.List;

/**
 * Created by Hydra.
 *
 * 1、如果改变列表的操作不在主线程里，会强制抛到主线程处理
 * 2、这样就会产生两个问题 1、多线程问题  2、方法返回值的问题
 */
public class KvoMainThreadList<T> extends KvoList<T> {

    public KvoMainThreadList(KvoSource source, String name) {
        super(source, name);
    }

    public KvoMainThreadList(KvoSource source, String name, List<T> list) {
        super(source, name, list);
    }

    @Override
    public void add(final int location, final T object) {
        if(isInMainThread()) {
            super.add(location, object);
        } else {
            ThreadBus.post(ThreadBus.Main, new Runnable() {
                @Override
                public void run() {
                    KvoMainThreadList.super.add(location, object);
                }
            });
        }
    }

    @Override
    public boolean add(final T object) {
        if(isInMainThread()) {
            return super.add(object);
        } else {
            ThreadBus.post(ThreadBus.Main, new Runnable() {
                @Override
                public void run() {
                    KvoMainThreadList.super.add(object);
                }
            });

            return true;
        }
    }

    @Override
    public boolean addAll(final int location, final Collection<? extends T> collection) {
        if(isInMainThread()) {
            return super.addAll(location, collection);
        } else {
            boolean result = collection != null && !collection.isEmpty();

            ThreadBus.post(ThreadBus.Main, new Runnable() {
                @Override
                public void run() {
                    KvoMainThreadList.super.addAll(location, collection);
                }
            });

            return result;
        }
    }

    @Override
    public boolean addAll(final Collection<? extends T> collection) {
        if(isInMainThread()) {
            return super.addAll(collection);
        } else {
            boolean result = collection != null && !collection.isEmpty();

            ThreadBus.post(ThreadBus.Main, new Runnable() {
                @Override
                public void run() {
                    KvoMainThreadList.super.addAll(collection);
                }
            });

            return result;
        }
    }

    @Override
    public void clear() {
        if(isInMainThread()) {
            super.clear();
        } else {
            ThreadBus.post(ThreadBus.Main, new Runnable() {
                @Override
                public void run() {
                    KvoMainThreadList.super.clear();
                }
            });
        }
    }

    @Override
    public T remove(final int location) {
        if(isInMainThread()) {
            return super.remove(location);
        } else {
            T t = get(location);

            ThreadBus.post(ThreadBus.Main, new Runnable() {
                @Override
                public void run() {
                    KvoMainThreadList.super.remove(location);
                }
            });

            return t;
        }
    }

    @Override
    public boolean remove(final Object object) {
        if(isInMainThread()) {
            return super.remove(object);
        } else {
            ThreadBus.post(ThreadBus.Main, new Runnable() {
                @Override
                public void run() {
                    KvoMainThreadList.super.remove(object);
                }
            });

            return true;
        }
    }

    @Override
    public boolean removeAll(final Collection<?> collection) {
        if(isInMainThread()) {
            return super.remove(collection);
        } else {
            ThreadBus.post(ThreadBus.Main, new Runnable() {
                @Override
                public void run() {
                    KvoMainThreadList.super.removeAll(collection);
                }
            });

            return true;
        }
    }

    @Override
    public boolean retainAll(final Collection<?> collection) {
        if(isInMainThread()) {
            return super.retainAll(collection);
        } else {
            ThreadBus.post(ThreadBus.Main, new Runnable() {
                @Override
                public void run() {
                    KvoMainThreadList.super.retainAll(collection);
                }
            });

            return true;
        }
    }

    @Override
    public T set(final int location, final T object) {
        if(isInMainThread()) {
            return super.set(location, object);
        } else {
            T t = get(location);

            ThreadBus.post(ThreadBus.Main, new Runnable() {
                @Override
                public void run() {
                    KvoMainThreadList.super.set(location, object);
                }
            });

            return t;
        }
    }

    @Override
    public void removeRange(final int fromIndex, final int toIndex) {
        if(isInMainThread()) {
            super.removeRange(fromIndex, toIndex);
        } else {
            ThreadBus.post(ThreadBus.Main, new Runnable() {
                @Override
                public void run() {
                    KvoMainThreadList.super.removeRange(fromIndex, toIndex);
                }
            });
        }
    }

    @Override
    public void move(final int fromIndex, final int toIndex) {
        if(isInMainThread()) {
            super.move(fromIndex, toIndex);
        } else {
            ThreadBus.post(ThreadBus.Main, new Runnable() {
                @Override
                public void run() {
                    KvoMainThreadList.super.move(fromIndex, toIndex);
                }
            });
        }
    }

    private static boolean isInMainThread() {
        return Looper.getMainLooper() == Looper.myLooper();
    }
}
